package com.xhx.vo;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

import lombok.Data;

/**
 * 通用返回结果-分页信息返回结果
 *
 * @author xhx
 */
@Data
public class PageInfoResult<T extends Serializable> implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	/**
	 * 总条数
	 */
	private long count;
	/**
	 * 页码
	 */
	private long pageNo;
	/**
	 * 页条数
	 */
	private long pageSize;
	/**
	 * 页数
	 */
	private long pages;
	/**
	 * 列表
	 */
	private List<T> list;

	/**
	 * 无结果返回
	 *
	 * @param <T>
	 * @return
	 */
	public static <T extends Serializable> PageInfoResult<T> empty() {
		PageInfoResult<T> p = new PageInfoResult<>();
		p.setList(Collections.emptyList());
		p.setCount(0);
		p.setPageNo(0);
		p.setPageSize(0);
		p.setPages(0);
		return p;
	}

	/**
	 * 将普通列表转换成分页数据
	 *
	 * @param pageNo   页码
	 * @param pageSize 一页记录数
	 * @param list     完整列表
	 * @param <T>
	 * @return
	 */
	public static <T extends Serializable> PageInfoResult<T> customResult(long pageNo, long pageSize, List<T> list) {
		PageInfoResult<T> p = new PageInfoResult<>();
		p.setPageNo(pageNo);
		p.setPageSize(pageSize);
		if (null == list || list.isEmpty() || 0 >= pageNo || 0 >= pageSize) {
			// 无数据时直接返回
			p.setCount(0);
			p.setPages(0);
			p.setList(Collections.emptyList());
			return p;
		}
		int size = list.size();
		p.setCount(size);
		if (pageSize >= size) {
			// 如果一页记录数大于等于总数量，则直接返回第一页
			p.setPageNo(1);
			p.setPages(1);
			p.setPageSize(size);
			p.setList(list);
			return p;
		}

		boolean isOver = (size % pageSize != 0);
		long pages = (size / pageSize) + (isOver ? 1 : 0);
		p.setPages(pages);
		int fromIndex = (int) ((pageNo - 1) * pageSize);
		int toIndex = size;
		if (pageNo > pages) {
			// 超出页码,直接返回最后一页
			fromIndex = (int) ((pages - 1) * pageSize);
			p.setPageNo(pages);
		} else if (pageNo < pages) {
			// 中间页
			toIndex = (int) (pageNo * pageSize);
		}
		p.setList(list.subList(fromIndex, toIndex));
		return p;
	}

	/**
	 * 转换page结果<br>
	 * 
	 * @param <E>
	 * @param <R>
	 * @param page     原分页结果
	 * @param function 转换函数
	 * @return
	 */
	@SuppressWarnings("hiding")
	public static <E extends Serializable, R extends Serializable> PageInfoResult<R> build(PageInfoResult<E> page,
			Function<E, R> function) {
		PageInfoResult<R> p = new PageInfoResult<>();
		p.setList(page.getList().stream().map(function).collect(Collectors.toList()));
		p.setCount(page.getCount());
		p.setPageNo(page.getPageNo());
		p.setPageSize(page.getPageSize());
		p.setPages(page.getPages());
		return p;
	}

}